#pragma once
#include "CGALDefine.h"

class ZMIntersection
{
	typedef K::Point_3 Point;
	typedef K::Line_3 Line;
	typedef K::Intersect_3 Intersect;
	typedef K::Segment_3 Segment;
	typedef K::Triangle_3 Triangle;
	typedef K::Direction_3 Direction;
	
public:
	static int Interscetion(const ZMLine& l1, const ZMLine& l2, ZMPoint3D& p1, ZMPoint3D& p2)
	{
		typedef CGAL::cpp11::result_of<Intersect(Line, Line)>::type IntersectType;
		int iRet = 0;
		IntersectType intData = CGAL::intersection(l1, l2);
		if (intData)
		{
			if (const Line* s = boost::get<Line>(&*intData))
			{
				iRet = 2;
				p1 = ZMPoint3D(s->point(0));
				p2 = ZMPoint3D(s->point(1));
			}
			else
			{
				iRet = 1;
				const Point* pnt = boost::get<Point >(&*intData);
				p1 = ZMPoint3D(*pnt);
			}
		}
		return iRet;
	}

	static int Interscetion(const ZMSegmengt& l1, const ZMSegmengt& l2, ZMPoint3D& p1, ZMPoint3D& p2)
	{
		typedef CGAL::cpp11::result_of<Intersect(Segment, Segment)>::type IntersectType;
		int iRet = 0;
		IntersectType intData = CGAL::intersection(l1, l2);
		if (intData)
		{
			if (const Segment* s = boost::get<Segment>(&*intData))
			{
				iRet = 2;
				p1 = ZMPoint3D(s->point(0));
				p2 = ZMPoint3D(s->point(1));
			}
			else
			{
				iRet = 1;
				const Point* pnt = boost::get<Point >(&*intData);
				p1 = ZMPoint3D(*pnt);
			}
		}
		return iRet;

	}

	static int Interscetion(const ZMSegmengt& l1, const ZMTriangle& tri, ZMPoint3D& p1, ZMPoint3D& p2)
	{
		typedef CGAL::cpp11::result_of<Intersect(Segment, Triangle)>::type IntersectType;
		int iRet = 0;
		IntersectType intData = CGAL::intersection(l1, tri);
		if (intData)
		{
			if (const Segment* s = boost::get<Segment>(&*intData))
			{
				iRet = 2;
				p1 = ZMPoint3D(s->point(0));
				p2 = ZMPoint3D(s->point(1));
			}
			else
			{
				iRet = 1;
				const Point* pnt = boost::get<Point >(&*intData);
				p1 = ZMPoint3D(*pnt);
			}
		}
		return iRet;
	}

	static void GetNearstPnt(const ZMLine& l1, const ZMLine& l2, ZMPoint3D& pntl1, ZMPoint3D& pntl2)
	{
		Direction d1 = l1.direction(); ZMPoint3D pntD1 = ZMPoint3D(d1.dx(), d1.dy(), d1.dz());
		Direction d2 = l2.direction(); ZMPoint3D pntD2 = ZMPoint3D(d2.dx(), d2.dy(), d2.dz());
		ZMPoint3D pntL1 = ZMPoint3D(l1.point(0));
		ZMPoint3D pntL2 = ZMPoint3D(l2.point(0));
		ZMPoint3D pntE = pntL2 - pntL1;
		ZMPoint3D pntCross[3];
		pntCross[0] = pntE.Crossed(pntD2);
		pntCross[1] = pntE.Crossed(pntD1);
		pntCross[2] = pntD1.Crossed(pntD2);
		double t[2];
		t[0] = pntCross[0].Dot(pntCross[2]);
		t[1] = pntCross[1].Dot(pntCross[2]);

		pntl1 = pntD1*t[0] + pntL1;
		pntl2 = pntD2*t[1] + pntL2;
	}

};

